String.prototype.asyncReplaceAll = async function (pattern, asyncFunc) {
  if (typeof asyncFunc === "string") {
    return this.replaceAll(pattern, replacer);
  }
  if (typeof asyncFunc !== "function") {
    throw new TypeError("The second argument Should be a function or a string");
  }
  let reg;
  if (typeof pattern === "string") {
    reg = new RegExp(pattern.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"), "g");
  } else if (pattern instanceof RegExp) {
    if (!pattern.global) {
      throw new TypeError("The pattern RegExp Should have the global flag set");
    }
    reg = new RegExp(pattern);
  } else {
    throw new TypeError("The pattern Should be a string or a global RegExp");
  }

  const result = [];
  let match,
    lastIndex = 0;
  while ((match = reg.exec(this)) !== null) {
    const item = asyncFunc(match[0]);
    const prefix = this.slice(lastIndex, match.index);
    lastIndex = match.index + match[0].length;
    result.push(prefix);
    result.push(item);
  }
  result.push(this.slice(lastIndex));
  return await Promise.all(result);
};
